Add files via upload#2291
Conversation
hackathon submission from team strike
Greptile SummaryThis PR adds a hackathon demo application (
Confidence Score: 3/5Safe to merge as a self-contained hackathon demo directory, but the HTTP control API has no authentication and binds to all interfaces, which is a real physical-safety concern when deployed on shared Wi-Fi. The robot control endpoints are openly accessible to anyone on the same network with no credentials required, and the server explicitly binds to 0.0.0.0. At a hackathon venue with shared Wi-Fi, an unintended command could cause the robot to move into people or equipment. The audio file path is also broken out of the box. The rest of the codebase is reasonably well-structured for a demo. dimensional-hackathon/demo_app/dashboard.py (unauthenticated command endpoints) and dimensional-hackathon/config.yaml (broken audio file path) need the most attention before this is run in any shared environment.
|
| Filename | Overview |
|---|---|
| dimensional-hackathon/demo_app/main.py | Central orchestrator wiring all subsystems together; 553 lines of async orchestration that is generally well-structured but the unauthenticated HTTP command API is the most significant concern in this file. |
| dimensional-hackathon/demo_app/dashboard.py | FastAPI app exposing robot commands with no auth, bound to 0.0.0.0; event_log list grows unbounded; WebSocket streaming logic is otherwise clean. |
| dimensional-hackathon/demo_app/patrol.py | Patrol loop and drive helpers; stop() sets a flag and awaits the task without cancelling it, meaning stop may take several seconds if a thread-backed move is in progress — acceptable for a demo but worth noting. |
| dimensional-hackathon/demo_app/robot.py | Go2Runner wraps the WebRTC connection, streams, and movement; connection timeout logic is solid; odom parser silently falls back on None values which is safe. |
| dimensional-hackathon/demo_app/telegram_bot.py | Owner-gated Telegram bot with dead-letter fallback for failed photo sends; retry delays (0, 1, 2, 4 s) are reasonable; caption formatting is clean. |
| dimensional-hackathon/demo_app/capture.py | Rolling frame buffer and snapshot/clip encoder; annotation format bug drops direction info when distance is None; otherwise thread-safe under Python GIL for deque access. |
| dimensional-hackathon/demo_app/types.py | Core dataclasses; Detection uses frozen=True with a mutable np.ndarray field making it technically unhashable despite the frozen annotation. |
| dimensional-hackathon/demo_app/config.py | Pydantic settings with env-var overrides; cooldown_sec field defined in DetectionConfig but never read by any detection logic; KeyError raised directly on missing TELEGRAM_* env vars. |
| dimensional-hackathon/demo_app/aisle.py | LiDAR point-cloud corridor detector; defensive filtering (finite check, height mask, cell counting) is thorough and correct. |
| dimensional-hackathon/demo_app/detector.py | YOLO wrapper with alias-based class matching; model loading is deferred to a thread to avoid blocking the event loop; class resolution logic handles both dict and list name maps. |
| dimensional-hackathon/config.yaml | Runtime config with a broken relative audio file path (../deploy_agentics_real/assets/alert.wav) that won't resolve in any standard setup. |
| dimensional-hackathon/demo_app/static/index.html | Single-page dashboard with canvas-based map, WebSocket video stream, and event log; event payload fields rendered via innerHTML without escaping but all data originates server-side from known command names. |
Sequence Diagram
sequenceDiagram
participant TG as Telegram Bot
participant Main as main.py (AsyncLoop)
participant Patrol as PatrolController
participant Robot as Go2Runner
participant Aisle as AisleCorridorDetector
participant Vision as CenterLaneVisionDetector
participant YOLO as YoloToolDetector
participant Capture as CaptureBuffer
participant Web as FastAPI Dashboard
Robot->>Main: on_frame(frame)
Robot->>Main: on_lidar(msg)
loop Monitor Loop (every 250ms)
Main->>Aisle: analyze(lidar_points)
Aisle-->>Main: AisleObservation
Main->>Vision: detect(frame)
Vision-->>Main: VisionObstruction
alt corridor blocked
Main->>YOLO: detect(frame)
YOLO-->>Main: list[Detection]
Main->>Capture: snapshot(event)
Capture-->>Main: jpg_path
Main->>TG: send_photo_alert(event, jpg_path)
Main->>Robot: audio.play(event)
Main->>Web: push_event(corridor_blocked)
end
end
TG->>Main: /patrol command
Main->>Patrol: start()
loop Patrol Cycle
Patrol->>Robot: drive_for_duration(forward)
Patrol->>Robot: drive_for_duration(yaw sweep)
end
Web->>Main: POST /api/command/stop
Main->>Patrol: stop()
Patrol-->>Main: (awaits task completion)
Comments Outside Diff (5)
-
dimensional-hackathon/demo_app/dashboard.py, line 572-586 (link)Unauthenticated robot-control endpoints on all interfaces
The HTTP server binds to
0.0.0.0(viaweb.hostdefault) and exposes/api/command/{name}with no authentication. Anyone on the same Wi-Fi can POSTpatrol,forward,back, etc. to physically move the robot without any credentials. At a hackathon venue with shared Wi-Fi this is a real concern — an unintendedforwardorpatrolcommand could cause the robot to collide with people or equipment. Consider restricting the host to127.0.0.1or adding a simple shared-secret header check, even for a demo. -
dimensional-hackathon/demo_app/capture.py, line 334-339 (link)Direction label silently dropped when distance is
NoneThe second list element uses implicit f-string concatenation followed by a ternary:
f"dir=..." f"dist=..." if condition else "dist=unknown". Python's grammar concatenates the two adjacent f-strings first, making the entire combined string the "then" branch. Whenobstruction_distance_m is None, the whole line collapses to just"dist=unknown"— thedir=portion is silently omitted from the snapshot annotation, losing useful debug context about which side the obstruction was on. -
dimensional-hackathon/demo_app/dashboard.py, line 532-547 (link)Unbounded
event_logcauses uncapped memory growthstate["event_log"]andweb_state["event_log"]are plain lists that are appended to throughout the session and never pruned. The/ws/eventsWebSocket handler uses alast_seencursor that also keeps growing. In a long-running patrol session every move, detection, command, and corridor event accumulates indefinitely. Consider capping the list (e.g., keep the last 1000 entries) or switching to acollections.deque(maxlen=...)to bound memory. -
dimensional-hackathon/demo_app/types.py, line 447-453 (link)frozen=Truedataclass with a mutablenp.ndarrayfieldDetectionis declaredfrozen=True(which implies immutability and attempts to make it hashable), but theframe: np.ndarrayfield is a mutable numpy array. NumPy arrays are not hashable, so any attempt to put aDetectionin asetor as adictkey will raiseTypeError: unhashable type: 'numpy.ndarray'. Thefrozenflag also gives a false impression of deep immutability — the array contents can still be mutated in place. Consider usingfrozen=False(or settingeq=False) and documenting the intent, or makingframea bytes blob. -
dimensional-hackathon/demo_app/config.py, line 441-447 (link)cooldown_secinDetectionConfigis never consumedDetectionConfigdeclares acooldown_secfield (defaulting to 300 s) andconfig.yamlsets it to 0, but no code inmain.pyordetector.pyreads this field. The per-detection cooldown logic that would use it is simply absent. The aisle monitor usescfg.aisle.alert_repeat_secfor its own repeat guard, but YOLO detections have no cooldown applied — every obstruction frame triggers a new Telegram alert as soon asalert_repeat_secpasses, regardless ofcooldown_sec. If the intent was to prevent re-alerting on the same object class within a cooldown window, this feature is not implemented.
Reviews (1): Last reviewed commit: "Add files via upload" | Re-trigger Greptile
| reclear_consecutive_frames: 2 | ||
|
|
||
| alert: | ||
| audio_file: ../deploy_agentics_real/assets/alert.wav |
There was a problem hiding this comment.
The
audio_file path is a relative reference to ../deploy_agentics_real/assets/alert.wav, which is outside the repo and almost certainly won't exist for anyone cloning this project. The app will fail silently (the _play_local_blocking catches exceptions) but no alert sound will ever play. The README doesn't mention this file or how to obtain it. Consider shipping a placeholder path (e.g., assets/alert.wav) and documenting how to provide the file.
| audio_file: ../deploy_agentics_real/assets/alert.wav | |
| audio_file: assets/alert.wav # Provide a WAV file at this path |
There was a problem hiding this comment.
hackathon submission from team strike